if lib and not lib.semafores then

lib.semafores = {}


function lib:lock_try(key, id)
	key = string.gsub(tostring(key), "[:\\/]", "@")
	if id then
		id = tostring(id)
	end
	
	if self.semafores[key] then
		self.semafores[key].count = self.semafores[key].count + 1
	
		if id then
			self.semafores[key].id[id] = self.semafores[key].id[id] + 1
		end
	else
		local sem_path = lib.path.semafores .. key .. ".sem"
		
		self:remove(sem_path)
		if self:exists(sem_path) then
			return
		end
		
		self.semafores[key] = {file = io.open(sem_path, "wb"), count = 1, id = {}}
		if not self.semafores[key].file or not self:exists(sem_path) then
			self.semafores[key] = nil
			fail("Semafore creation error")
			return
		end
	
		if id then
			self.semafores[key].id[id] = 1
		end
	end
	
	return self.semafores[key].count
end


function lib:singleton(key)
	--message("singleton " .. key)
	local lock, remote = self:locked(key)
	
	if lock then
		return not remote
	else
		return self:lock_try(key)
	end
end


function lib:lock(key, id)
	local count
	
	while true do
		count = self:lock_try(key, id)
		
		if count then
			break
		end
		
		sleep(200)
	end
	
	return count
end


function lib:unlock(key, id)
	key = string.gsub(tostring(key), "[:\\/]", "@")
	if id then
		id = tostring(id)
	end
	
	if self.semafores[key] and (not id or self.semafores[key].id[id]) then
		self.semafores[key].count = self.semafores[key].count - 1
	
		if id then
			self.semafores[key].id[id] = self.semafores[key].id[id] - 1
			
			if self.semafores[key].id[id] <= 0 then
				self.semafores[key].id[id] = nil
			end
		end
		
		if self.semafores[key].count <= 0 then
			local sem_path = lib.path.semafores .. key .. ".sem"
			
			io.close(self.semafores[key].file)
			self.semafores[key] = nil
			
			self:remove(sem_path)
		end
	end
end


function lib:locked(key, id)
	key = string.gsub(tostring(key), "[:\\/]", "@")
	
	if self.semafores[key] then
		return not id or self.semafores[key].id[id]		-- this script lock
	end
	
	if self:lock(key, id) then
		self:unlock(key, id)
	else
		return true, true								-- another script lock
	end
end


end -- of file
